/**
 * create by zhangpu
 * date:2015年3月2日
 */
package com.acooly.module.openapi.client.provider.fuyou;

import com.acooly.module.openapi.client.api.AbstractApiServiceClient;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.api.exception.ApiServerException;
import com.acooly.module.openapi.client.api.marshal.ApiMarshal;
import com.acooly.module.openapi.client.api.marshal.ApiUnmarshal;
import com.acooly.module.openapi.client.api.message.PostRedirect;
import com.acooly.module.openapi.client.api.transport.Transport;
import com.acooly.module.openapi.client.provider.fuyou.domain.FuyouNotify;
import com.acooly.module.openapi.client.provider.fuyou.domain.FuyouRequest;
import com.acooly.module.openapi.client.provider.fuyou.domain.FuyouResponse;
import com.acooly.module.openapi.client.provider.fuyou.enums.FuyouServiceEnum;
import com.acooly.module.openapi.client.provider.fuyou.enums.FuyouServiceTypeEnum;
import com.acooly.module.openapi.client.provider.fuyou.marshall.*;
import com.acooly.module.openapi.client.provider.fuyou.utils.DESCoderFuyou;
import com.acooly.module.openapi.client.provider.fuyou.utils.HttpServletRequestUtil;
import com.acooly.module.openapi.client.provider.fuyou.utils.StringHelper;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import sun.applet.Main;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.net.URLEncoder;
import java.util.Map;

/**
 * ApiService执行器
 *
 * @author zhangpu
 */
@Component("fuyouApiServiceClient")
@Slf4j
public class FuyouApiServiceClient
        extends AbstractApiServiceClient<FuyouRequest, FuyouResponse, FuyouNotify, FuyouResponse> {

    public static final String PROVIDER_NAME = "fuyou";

    @Resource(name = "fuyouHttpTransport")
    private Transport transport;
    @Resource(name = "fuyouRequestMarshall")
    private FuyouRequestMarshall requestMarshal;
    @Resource(name = "fuyouRedirectMarshall")
    private FuyouRedirectMarshall redirectMarshal;

    @Resource(name = "fuyouRedirectPostMarshall")
    private FuyouRedirectPostMarshall fuyouRedirectPostMarshall;

    @Autowired
    private FuyouResponseUnmarshall responseUnmarshal;
    @Autowired
    private FuyouNotifyUnmarshall notifyUnmarshal;
    @Autowired
    private FuyouReturnUnmarshall returnUnmarshal;

    @Autowired
    private OpenAPIClientFuyouProperties openAPIClientFuiouProperties;

    @Override
    public FuyouResponse execute(FuyouRequest request) {
        try {
            beforeExecute(request);
            String url = request.getGatewayUrl();
            String requestMessage;
            if(FuyouServiceTypeEnum.WI.equals(FuyouServiceEnum.find(request.getService()).getType())) {
                requestMessage = requestMarshal.withdrawMarshal(request);
            } else {
                requestMessage = getRequestMarshal().marshal(request);
            }
            String responseMessage = getTransport().request(requestMessage, url).getBody();
            FuyouResponse t = getResponseUnmarshal().unmarshal(responseMessage, request.getService());
            afterExecute(t);
            return t;
        } catch (ApiServerException ose) {
            log.error("服务器:" + ose.getMessage(), ose);
            throw ose;
        } catch (ApiClientException oce) {
            log.error("客户端:" + oce.getMessage(), oce);
            throw oce;
        } catch (Exception e) {
            log.error("内部错误:" + e.getMessage(), e);
            throw new ApiClientException("内部错误:" + e.getMessage());
        }
    }

    @Override
    public String redirectGet(FuyouRequest request) {
        PostRedirect postRedirect = redirectPost(request);
        String fromHtml = StringHelper.netbankBuildFormHtml(postRedirect.getRedirectUrl(), postRedirect.getFormDatas(), FuyouConstants.NETBANK_NAME);
        return fromHtml;
    }

    @Override
    public PostRedirect redirectPost(FuyouRequest request) {
        try {
            beforeExecute(request);
            PostRedirect postRedirect = fuyouRedirectPostMarshall.marshal(request);
            return postRedirect;
        } catch (ApiServerException ose) {
            log.error("服务器:" + ose.getMessage(), ose);
            throw ose;
        } catch (ApiClientException oce) {
            log.error("客户端:" + oce.getMessage(), oce);
            throw oce;
        } catch (Exception e) {
            log.error("内部错误:" + e.getMessage(), e);
            throw new ApiClientException("内部错误:" + e.getMessage());
        }
    }


    public FuyouNotify notice(HttpServletRequest request, String serviceKey) {
        try {
            Map<String, String> notifyData = HttpServletRequestUtil.getNoticeDateMap(request);
            FuyouNotify notify = getNoticeUnmarshal().unmarshal(notifyData, serviceKey);
            afterNotice(notify);
            log.info("通知报文：{}", JSON.toJSONString(notify));
            return notify;
        } catch (ApiClientException oce) {
            log.warn("客户端:{}", oce.getMessage());
            throw oce;
        } catch (Exception e) {
            log.warn("内部错误:{}", e.getMessage());
            throw new ApiClientException("内部错误:" + e.getMessage());
        }
    }

    @Override
    protected ApiMarshal<String, FuyouRequest> getRequestMarshal() {
        return this.requestMarshal;
    }

    @Override
    protected ApiUnmarshal<FuyouResponse, String> getResponseUnmarshal() {
        return this.responseUnmarshal;
    }

    @Override
    protected ApiMarshal<String, FuyouRequest> getRedirectMarshal() {
        return this.redirectMarshal;
    }

    @Override
    protected ApiUnmarshal<FuyouNotify, Map<String, String>> getNoticeUnmarshal() {
        return this.notifyUnmarshal;
    }

    @Override
    protected Transport getTransport() {
        return this.transport;
    }


    public ApiUnmarshal<FuyouResponse, Map<String, String>> getReturnUnmarshal() {
        return this.returnUnmarshal;
    }

    @Override
    public String getName() {
        return PROVIDER_NAME;
    }


}
